home *** CD-ROM | disk | FTP | other *** search
/ CD/PC Actual 31 / PC Actual CD 31.iso / dists / SRC / SLIBEXEC.AA / SLIBEXEC / libexec / rbootd / utils.c < prev   
Encoding:
C/C++ Source or Header  |  1997-11-24  |  13.9 KB  |  560 lines

  1. /*
  2.  * Copyright (c) 1988, 1992 The University of Utah and the Center
  3.  *    for Software Science (CSS).
  4.  * Copyright (c) 1992, 1993
  5.  *    The Regents of the University of California.  All rights reserved.
  6.  *
  7.  * This code is derived from software contributed to Berkeley by
  8.  * the Center for Software Science of the University of Utah Computer
  9.  * Science Department.  CSS requests users of this software to return
  10.  * to css-dist@cs.utah.edu any improvements that they make and grant
  11.  * CSS redistribution rights.
  12.  *
  13.  * Redistribution and use in source and binary forms, with or without
  14.  * modification, are permitted provided that the following conditions
  15.  * are met:
  16.  * 1. Redistributions of source code must retain the above copyright
  17.  *    notice, this list of conditions and the following disclaimer.
  18.  * 2. Redistributions in binary form must reproduce the above copyright
  19.  *    notice, this list of conditions and the following disclaimer in the
  20.  *    documentation and/or other materials provided with the distribution.
  21.  * 3. All advertising materials mentioning features or use of this software
  22.  *    must display the following acknowledgement:
  23.  *    This product includes software developed by the University of
  24.  *    California, Berkeley and its contributors.
  25.  * 4. Neither the name of the University nor the names of its contributors
  26.  *    may be used to endorse or promote products derived from this software
  27.  *    without specific prior written permission.
  28.  *
  29.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  30.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  31.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  32.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  33.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  34.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  35.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  36.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  37.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  38.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  39.  * SUCH DAMAGE.
  40.  *
  41.  *    from: @(#)utils.c    8.1 (Berkeley) 6/4/93
  42.  *
  43.  * From: Utah Hdr: utils.c 3.1 92/07/06
  44.  * Author: Jeff Forys, University of Utah CSS
  45.  */
  46.  
  47. #ifndef lint
  48. #if 0
  49. static const char sccsid[] = "@(#)utils.c    8.1 (Berkeley) 6/4/93";
  50. #endif
  51. static const char rcsid[] =
  52.     "$Id: utils.c,v 1.4 1997/11/24 07:33:42 charnier Exp $";
  53. #endif /* not lint */
  54.  
  55. #include <sys/param.h>
  56. #include <sys/time.h>
  57.  
  58. #include <fcntl.h>
  59. #include <signal.h>
  60. #include <stdio.h>
  61. #include <stdlib.h>
  62. #include <string.h>
  63. #include <syslog.h>
  64. #include <time.h>
  65. #include <unistd.h>
  66. #include "defs.h"
  67.  
  68. /*
  69. **  DispPkt -- Display the contents of an RMPCONN packet.
  70. **
  71. **    Parameters:
  72. **        rconn - packet to be displayed.
  73. **        direct - direction packet is going (DIR_*).
  74. **
  75. **    Returns:
  76. **        Nothing.
  77. **
  78. **    Side Effects:
  79. **        None.
  80. */
  81. void
  82. DispPkt(rconn, direct)
  83.     RMPCONN *rconn;
  84.     int direct;
  85. {
  86.     static char BootFmt[] = "\t\tRetCode:%u SeqNo:%lx SessID:%x Vers:%u";
  87.     static char ReadFmt[] = "\t\tRetCode:%u Offset:%lx SessID:%x\n";
  88.  
  89.     struct tm *tmp;
  90.     struct rmp_packet *rmp;
  91.     int i, omask;
  92.     u_int32_t t;
  93.  
  94.     /*
  95.      *  Since we will be working with RmpConns as well as DbgFp, we
  96.      *  must block signals that can affect either.
  97.      */
  98.     omask = sigblock(sigmask(SIGHUP)|sigmask(SIGUSR1)|sigmask(SIGUSR2));
  99.  
  100.     if (DbgFp == NULL) {            /* sanity */
  101.         (void) sigsetmask(omask);
  102.         return;
  103.     }
  104.  
  105.     /* display direction packet is going using '>>>' or '<<<' */
  106.     fputs((direct==DIR_RCVD)?"<<< ":(direct==DIR_SENT)?">>> ":"", DbgFp);
  107.  
  108.     /* display packet timestamp */
  109.     tmp = localtime((time_t *)&rconn->tstamp.tv_sec);
  110.     fprintf(DbgFp, "%02d:%02d:%02d.%06ld   ", tmp->tm_hour, tmp->tm_min,
  111.             tmp->tm_sec, rconn->tstamp.tv_usec);
  112.  
  113.     /* display src or dst addr and information about network interface */
  114.     fprintf(DbgFp, "Addr: %s   Intf: %s\n", EnetStr(rconn), IntfName);
  115.  
  116.     rmp = &rconn->rmp;
  117.  
  118.     /* display IEEE 802.2 Logical Link Control header */
  119.     (void) fprintf(DbgFp, "\t802.2 LLC: DSAP:%x SSAP:%x CTRL:%x\n",
  120.                rmp->hp_llc.dsap, rmp->hp_llc.ssap, ntohs(rmp->hp_llc.cntrl));
  121.  
  122.     /* display HP extensions to 802.2 Logical Link Control header */
  123.     (void) fprintf(DbgFp, "\tHP Ext:    DXSAP:%x SXSAP:%x\n",
  124.                    ntohs(rmp->hp_llc.dxsap), ntohs(rmp->hp_llc.sxsap));
  125.  
  126.     /*
  127.      *  Display information about RMP packet using type field to
  128.      *  determine what kind of packet this is.
  129.      */
  130.     switch(rmp->r_type) {
  131.         case RMP_BOOT_REQ:        /* boot request */
  132.             (void) fprintf(DbgFp, "\tBoot Request:");
  133.             GETWORD(rmp->r_brq.rmp_seqno, t);
  134.             if (ntohs(rmp->r_brq.rmp_session) == RMP_PROBESID) {
  135.                 if (WORDZE(rmp->r_brq.rmp_seqno))
  136.                     fputs(" (Send Server ID)", DbgFp);
  137.                 else
  138.                     fprintf(DbgFp," (Send Filename #%u)",t);
  139.             }
  140.             (void) fputc('\n', DbgFp);
  141.             (void) fprintf(DbgFp, BootFmt, rmp->r_brq.rmp_retcode,
  142.                     t, ntohs(rmp->r_brq.rmp_session),
  143.                     ntohs(rmp->r_brq.rmp_version));
  144.             (void) fprintf(DbgFp, "\n\t\tMachine Type: ");
  145.             for (i = 0; i < RMP_MACHLEN; i++)
  146.                 (void) fputc(rmp->r_brq.rmp_machtype[i], DbgFp);
  147.             DspFlnm(rmp->r_brq.rmp_flnmsize, &rmp->r_brq.rmp_flnm);
  148.             break;
  149.         case RMP_BOOT_REPL:        /* boot reply */
  150.             fprintf(DbgFp, "\tBoot Reply:\n");
  151.             GETWORD(rmp->r_brpl.rmp_seqno, t);
  152.             (void) fprintf(DbgFp, BootFmt, rmp->r_brpl.rmp_retcode,
  153.                     t, ntohs(rmp->r_brpl.rmp_session),
  154.                     ntohs(rmp->r_brpl.rmp_version));
  155.             DspFlnm(rmp->r_brpl.rmp_flnmsize,&rmp->r_brpl.rmp_flnm);
  156.             break;
  157.         case RMP_READ_REQ:        /* read request */
  158.             (void) fprintf(DbgFp, "\tRead Request:\n");
  159.             GETWORD(rmp->r_rrq.rmp_offset, t);
  160.             (void) fprintf(DbgFp, ReadFmt, rmp->r_rrq.rmp_retcode,
  161.                     t, ntohs(rmp->r_rrq.rmp_session));
  162.             (void) fprintf(DbgFp, "\t\tNoOfBytes: %u\n",
  163.                     ntohs(rmp->r_rrq.rmp_size));
  164.             break;
  165.         case RMP_READ_REPL:        /* read reply */
  166.             (void) fprintf(DbgFp, "\tRead Reply:\n");
  167.             GETWORD(rmp->r_rrpl.rmp_offset, t);
  168.             (void) fprintf(DbgFp, ReadFmt, rmp->r_rrpl.rmp_retcode,
  169.                     t, ntohs(rmp->r_rrpl.rmp_session));
  170.             (void) fprintf(DbgFp, "\t\tNoOfBytesSent: %d\n",
  171.                     rconn->rmplen - RMPREADSIZE(0));
  172.             break;
  173.         case RMP_BOOT_DONE:        /* boot complete */
  174.             (void) fprintf(DbgFp, "\tBoot Complete:\n");
  175.             (void) fprintf(DbgFp, "\t\tRetCode:%u SessID:%x\n",
  176.                     rmp->r_done.rmp_retcode,
  177.                     ntohs(rmp->r_done.rmp_session));
  178.             break;
  179.         default:            /* ??? */
  180.             (void) fprintf(DbgFp, "\tUnknown Type:(%d)\n",
  181.                 rmp->r_type);
  182.     }
  183.     (void) fputc('\n', DbgFp);
  184.     (void) fflush(DbgFp);
  185.  
  186.     (void) sigsetmask(omask);        /* reset old signal mask */
  187. }
  188.  
  189.  
  190. /*
  191. **  GetEtherAddr -- convert an RMP (Ethernet) address into a string.
  192. **
  193. **    An RMP BOOT packet has been received.  Look at the type field
  194. **    and process Boot Requests, Read Requests, and Boot Complete
  195. **    packets.  Any other type will be dropped with a warning msg.
  196. **
  197. **    Parameters:
  198. **        addr - array of RMP_ADDRLEN bytes.
  199. **
  200. **    Returns:
  201. **        Pointer to static string representation of `addr'.
  202. **
  203. **    Side Effects:
  204. **        None.
  205. **
  206. **    Warnings:
  207. **        - The return value points to a static buffer; it must
  208. **          be copied if it's to be saved.
  209. */
  210. char *
  211. GetEtherAddr(addr)
  212.     u_int8_t *addr;
  213. {
  214.     static char Hex[] = "0123456789abcdef";
  215.     static char etherstr[RMP_ADDRLEN*3];
  216.     int i;
  217.     char *cp;
  218.  
  219.     /*
  220.      *  For each byte in `addr', convert it to "<hexchar><hexchar>:".
  221.      *  The last byte does not get a trailing `:' appended.
  222.      */
  223.     i = 0;
  224.     cp = etherstr;
  225.     for(;;) {
  226.         *cp++ = Hex[*addr >> 4 & 0xf];
  227.         *cp++ = Hex[*addr++ & 0xf];
  228.         if (++i == RMP_ADDRLEN)
  229.             break;
  230.         *cp++ = ':';
  231.     }
  232.     *cp = '\0';
  233.  
  234.     return(etherstr);
  235. }
  236.  
  237.  
  238. /*
  239. **  DispFlnm -- Print a string of bytes to DbgFp (often, a file name).
  240. **
  241. **    Parameters:
  242. **        size - number of bytes to print.
  243. **        flnm - address of first byte.
  244. **
  245. **    Returns:
  246. **        Nothing.
  247. **
  248. **    Side Effects:
  249. **        - Characters are sent to `DbgFp'.
  250. */
  251. void
  252. DspFlnm(size, flnm)
  253.     u_int size;
  254.     char *flnm;
  255. {
  256.     int i;
  257.  
  258.     (void) fprintf(DbgFp, "\n\t\tFile Name (%u): <", size);
  259.     for (i = 0; i < size; i++)
  260.         (void) fputc(*flnm++, DbgFp);
  261.     (void) fputs(">\n", DbgFp);
  262. }
  263.  
  264.  
  265. /*
  266. **  NewClient -- allocate memory for a new CLIENT.
  267. **
  268. **    Parameters:
  269. **        addr - RMP (Ethernet) address of new client.
  270. **
  271. **    Returns:
  272. **        Ptr to new CLIENT or NULL if we ran out of memory.
  273. **
  274. **    Side Effects:
  275. **        - Memory will be malloc'd for the new CLIENT.
  276. **        - If malloc() fails, a log message will be generated.
  277. */
  278. CLIENT *
  279. NewClient(addr)
  280.     u_int8_t *addr;
  281. {
  282.     CLIENT *ctmp;
  283.  
  284.     if ((ctmp = (CLIENT *) malloc(sizeof(CLIENT))) == NULL) {
  285.         syslog(LOG_ERR, "NewClient: out of memory (%s)",
  286.                GetEtherAddr(addr));
  287.         return(NULL);
  288.     }
  289.  
  290.     memset(ctmp, 0, sizeof(CLIENT));
  291.     memmove(&ctmp->addr[0], addr, RMP_ADDRLEN);
  292.     return(ctmp);
  293. }
  294.  
  295. /*
  296. **  FreeClient -- free linked list of Clients.
  297. **
  298. **    Parameters:
  299. **        None.
  300. **
  301. **    Returns:
  302. **        Nothing.
  303. **
  304. **    Side Effects:
  305. **        - All malloc'd memory associated with the linked list of
  306. **          CLIENTS will be free'd; `Clients' will be set to NULL.
  307. **
  308. **    Warnings:
  309. **        - This routine must be called with SIGHUP blocked.
  310. */
  311. void
  312. FreeClients()
  313. {
  314.     CLIENT *ctmp;
  315.  
  316.     while (Clients != NULL) {
  317.         ctmp = Clients;
  318.         Clients = Clients->next;
  319.         FreeClient(ctmp);
  320.     }
  321. }
  322.  
  323. /*
  324. **  NewStr -- allocate memory for a character array.
  325. **
  326. **    Parameters:
  327. **        str - null terminated character array.
  328. **
  329. **    Returns:
  330. **        Ptr to new character array or NULL if we ran out of memory.
  331. **
  332. **    Side Effects:
  333. **        - Memory will be malloc'd for the new character array.
  334. **        - If malloc() fails, a log message will be generated.
  335. */
  336. char *
  337. NewStr(str)
  338.     char *str;
  339. {
  340.     char *stmp;
  341.  
  342.     if ((stmp = (char *)malloc((unsigned) (strlen(str)+1))) == NULL) {
  343.         syslog(LOG_ERR, "NewStr: out of memory (%s)", str);
  344.         return(NULL);
  345.     }
  346.  
  347.     (void) strcpy(stmp, str);
  348.     return(stmp);
  349. }
  350.  
  351. /*
  352. **  To save time, NewConn and FreeConn maintain a cache of one RMPCONN
  353. **  in `LastFree' (defined below).
  354. */
  355.  
  356. static RMPCONN *LastFree = NULL;
  357.  
  358. /*
  359. **  NewConn -- allocate memory for a new RMPCONN connection.
  360. **
  361. **    Parameters:
  362. **        rconn - initialization template for new connection.
  363. **
  364. **    Returns:
  365. **        Ptr to new RMPCONN or NULL if we ran out of memory.
  366. **
  367. **    Side Effects:
  368. **        - Memory may be malloc'd for the new RMPCONN (if not cached).
  369. **        - If malloc() fails, a log message will be generated.
  370. */
  371. RMPCONN *
  372. NewConn(rconn)
  373.     RMPCONN *rconn;
  374. {
  375.     RMPCONN *rtmp;
  376.  
  377.     if (LastFree == NULL) {        /* nothing cached; make a new one */
  378.         if ((rtmp = (RMPCONN *) malloc(sizeof(RMPCONN))) == NULL) {
  379.             syslog(LOG_ERR, "NewConn: out of memory (%s)",
  380.                    EnetStr(rconn));
  381.             return(NULL);
  382.         }
  383.     } else {            /* use the cached RMPCONN */
  384.         rtmp = LastFree;
  385.         LastFree = NULL;
  386.     }
  387.  
  388.     /*
  389.      *  Copy template into `rtmp', init file descriptor to `-1' and
  390.      *  set ptr to next elem NULL.
  391.      */
  392.     memmove((char *)rtmp, (char *)rconn, sizeof(RMPCONN));
  393.     rtmp->bootfd = -1;
  394.     rtmp->next = NULL;
  395.  
  396.     return(rtmp);
  397. }
  398.  
  399. /*
  400. **  FreeConn -- Free memory associated with an RMPCONN connection.
  401. **
  402. **    Parameters:
  403. **        rtmp - ptr to RMPCONN to be free'd.
  404. **
  405. **    Returns:
  406. **        Nothing.
  407. **
  408. **    Side Effects:
  409. **        - Memory associated with `rtmp' may be free'd (or cached).
  410. **        - File desc associated with `rtmp->bootfd' will be closed.
  411. */
  412. void
  413. FreeConn(rtmp)
  414.     RMPCONN *rtmp;
  415. {
  416.     /*
  417.      *  If the file descriptor is in use, close the file.
  418.      */
  419.     if (rtmp->bootfd >= 0) {
  420.         (void) close(rtmp->bootfd);
  421.         rtmp->bootfd = -1;
  422.     }
  423.  
  424.     if (LastFree == NULL)        /* cache for next time */
  425.         rtmp = LastFree;
  426.     else                /* already one cached; free this one */
  427.         free((char *)rtmp);
  428. }
  429.  
  430. /*
  431. **  FreeConns -- free linked list of RMPCONN connections.
  432. **
  433. **    Parameters:
  434. **        None.
  435. **
  436. **    Returns:
  437. **        Nothing.
  438. **
  439. **    Side Effects:
  440. **        - All malloc'd memory associated with the linked list of
  441. **          connections will be free'd; `RmpConns' will be set to NULL.
  442. **        - If LastFree is != NULL, it too will be free'd & NULL'd.
  443. **
  444. **    Warnings:
  445. **        - This routine must be called with SIGHUP blocked.
  446. */
  447. void
  448. FreeConns()
  449. {
  450.     RMPCONN *rtmp;
  451.  
  452.     while (RmpConns != NULL) {
  453.         rtmp = RmpConns;
  454.         RmpConns = RmpConns->next;
  455.         FreeConn(rtmp);
  456.     }
  457.  
  458.     if (LastFree != NULL) {
  459.         free((char *)LastFree);
  460.         LastFree = NULL;
  461.     }
  462. }
  463.  
  464. /*
  465. **  AddConn -- Add a connection to the linked list of connections.
  466. **
  467. **    Parameters:
  468. **        rconn - connection to be added.
  469. **
  470. **    Returns:
  471. **        Nothing.
  472. **
  473. **    Side Effects:
  474. **        - RmpConn will point to new connection.
  475. **
  476. **    Warnings:
  477. **        - This routine must be called with SIGHUP blocked.
  478. */
  479. void
  480. AddConn(rconn)
  481.     RMPCONN *rconn;
  482. {
  483.     if (RmpConns != NULL)
  484.         rconn->next = RmpConns;
  485.     RmpConns = rconn;
  486. }
  487.  
  488. /*
  489. **  FindConn -- Find a connection in the linked list of connections.
  490. **
  491. **    We use the RMP (Ethernet) address as the basis for determining
  492. **    if this is the same connection.  According to the Remote Maint
  493. **    Protocol, we can only have one connection with any machine.
  494. **
  495. **    Parameters:
  496. **        rconn - connection to be found.
  497. **
  498. **    Returns:
  499. **        Matching connection from linked list or NULL if not found.
  500. **
  501. **    Side Effects:
  502. **        None.
  503. **
  504. **    Warnings:
  505. **        - This routine must be called with SIGHUP blocked.
  506. */
  507. RMPCONN *
  508. FindConn(rconn)
  509.     RMPCONN *rconn;
  510. {
  511.     RMPCONN *rtmp;
  512.  
  513.     for (rtmp = RmpConns; rtmp != NULL; rtmp = rtmp->next)
  514.         if (bcmp((char *)&rconn->rmp.hp_hdr.saddr[0],
  515.                  (char *)&rtmp->rmp.hp_hdr.saddr[0], RMP_ADDRLEN) == 0)
  516.             break;
  517.  
  518.     return(rtmp);
  519. }
  520.  
  521. /*
  522. **  RemoveConn -- Remove a connection from the linked list of connections.
  523. **
  524. **    Parameters:
  525. **        rconn - connection to be removed.
  526. **
  527. **    Returns:
  528. **        Nothing.
  529. **
  530. **    Side Effects:
  531. **        - If found, an RMPCONN will cease to exist and it will
  532. **          be removed from the linked list.
  533. **
  534. **    Warnings:
  535. **        - This routine must be called with SIGHUP blocked.
  536. */
  537. void
  538. RemoveConn(rconn)
  539.     RMPCONN *rconn;
  540. {
  541.     RMPCONN *thisrconn, *lastrconn;
  542.  
  543.     if (RmpConns == rconn) {        /* easy case */
  544.         RmpConns = RmpConns->next;
  545.         FreeConn(rconn);
  546.     } else {                /* must traverse linked list */
  547.         lastrconn = RmpConns;            /* set back ptr */
  548.         thisrconn = lastrconn->next;        /* set current ptr */
  549.         while (thisrconn != NULL) {
  550.             if (rconn == thisrconn) {        /* found it */
  551.                 lastrconn->next = thisrconn->next;
  552.                 FreeConn(thisrconn);
  553.                 break;
  554.             }
  555.             lastrconn = thisrconn;
  556.             thisrconn = thisrconn->next;
  557.         }
  558.     }
  559. }
  560.